#include <vector>
#include <string>
#include "wx/wx.h"
#include <sqlite3.h>
#include <sqlite3util.h>
#include <string>
#include <iostream>
#include "dbi.h"

IMSITable::IMSITable()
    :m_DB(NULL), m_imsilist_stmt(NULL)
{
    
}

IMSITable::IMSITable(const char * wPath):m_imsilist_stmt(NULL)
{
    //open TMSI table
    int rc = sqlite3_open(wPath, &m_DB);
    if (rc) 
    {
        wxString strMsg;
        //strMsg.Printf(_("Cannot open IMSITable database at %s"), wPath);
        //wxMessageBox(strMsg, _("IMSI List"), wxOK);
        std::cerr<<"Cannot open database" << wPath << ":" << sqlite3_errmsg(m_DB);
        sqlite3_close(m_DB);
        m_DB = NULL;
        return;
    }
}

IMSITable::~IMSITable()
{
    if (m_DB) sqlite3_close(m_DB);
}

void IMSITable::preIMSIList()
{
    std::string query = "SELECT IMSI FROM TMSI_TABLE";
    if (sqlite3_prepare_statement(m_DB, &m_imsilist_stmt, query.c_str())) return;
}

bool IMSITable::IMSIhasnext()
{
    int src = sqlite3_run_query(m_DB, m_imsilist_stmt);
    if (src == SQLITE_ROW)
        return true;
    else
        return false;
}

wxString IMSITable::getIMSI()
{
    char * strIMSI = (char *)sqlite3_column_text(m_imsilist_stmt, 0);
    return wxString(strIMSI, wxConvUTF8);
    
}
 
int IMSITable::delIMSI(const char* IMSI)
{
    sqlite3_stmt * stmt;
    std::string query = "delete from TMSI_TABLE where IMSI=\'";
    query.append(IMSI);
    query.append("\'");
    if (sqlite3_prepare_statement(m_DB, &stmt, query.c_str()))
    {
        wxMessageBox(_("Cannot prepare statment"), _("DB Error"), wxOK|wxICON_ERROR);
        std::cerr<<"Cannot prepare statment"<<query << ":" << sqlite3_errmsg(m_DB);
        return -1;
    }
    else
    {
        int rc;
        rc = sqlite3_run_query(m_DB, stmt);
        if ((rc != SQLITE_DONE) && (rc != SQLITE_ROW)) return -1;
        return 0;
    }
}

void IMSITable::stmtClose()
{
    if(m_imsilist_stmt) sqlite3_finalize(m_imsilist_stmt);
}

void IMSITable::close()
{
    //~IMSITable();
}

SingleColDBI::SingleColDBI(const char * wPath, const char * query)
{
    //TODO: should throw exception to handle error
    if (wPath == NULL)
    {
        return;
    }
    int rc = sqlite3_open(wPath, &m_DB);
    if (rc) 
    {
        wxString strMsg;
        //strMsg.Printf(_("Cannot open IMSITable database at %s"), wPath);
        //wxMessageBox(strMsg, _("IMSI List"), wxOK);
        std::cerr<<"Cannot open database" << wPath << ":" << sqlite3_errmsg(m_DB);
        wxMessageBox(_("Cannot open database"), _("DB Error"), wxOK|wxICON_ERROR);
        sqlite3_close(m_DB);
        m_DB = NULL;
        return;
    }
    if (NULL != query)
    {
        if (sqlite3_prepare_statement(m_DB, &m_stmt, query)) 
        {
            std::cerr<<"Cannot prepare statment" << query << ":" << sqlite3_errmsg(m_DB);
            wxMessageBox(_("Cannot prepare statment"), _("DB Error"), wxOK|wxICON_ERROR);
        }
    }
    else 
    {
        m_stmt = NULL;
    }
}

SingleColDBI::~SingleColDBI()
{
    if (m_DB) sqlite3_close(m_DB);
}

bool SingleColDBI::hasnext() const
{
    if (m_stmt == NULL) return false;
    int src = sqlite3_run_query(m_DB, m_stmt);
    if (src == SQLITE_ROW)
        return true;
    else
        return false; 
}

void SingleColDBI::prepareQuery(const char * query) 
{
    if (NULL == m_DB) return;
    if (sqlite3_prepare_statement(m_DB, &m_stmt, query)) 
    {
        std::cerr<<"Cannot prepare statment" << query << ":" << sqlite3_errmsg(m_DB);
        wxMessageBox(_("Cannot prepare statment"), _("DB Error"), wxOK|wxICON_ERROR);
    }
}

int SingleColDBI::runQuery()
{
    int ret = -1;
    wxString strMsg;
    if (NULL == m_DB) return ret;
    
    ret = sqlite3_run_query(m_DB, m_stmt);
    if ((ret != SQLITE_DONE) && (ret != SQLITE_ROW))
    {
        strMsg.Printf(_("Database run query failed"));
        wxMessageBox(strMsg);
        return -1;
    }
    return 0;   
}

wxString SingleColDBI::getVal(int colidx) const
{
    if (m_stmt == NULL) return _T("");
    char * strVal= (char *)sqlite3_column_text(m_stmt, colidx);
    return wxString(strVal, wxConvUTF8);    
}

void SingleColDBI::stmtClose() 
{
    if (m_stmt == NULL) return;
    sqlite3_finalize(m_stmt);   
    m_stmt = NULL;
}

void SingleColDBI::close()
{
    //~SingleColDBI();
}
